package com.mostka.rpc.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;

import com.google.gwt.core.ext.TreeLogger;

public class Compiler {
	public static void doCompilation (TreeLogger logger, DynamicJavaFileObject javaFileObject) throws FileNotFoundException{
        JavaFileObject javaFileObjects[] = new JavaFileObject[]{javaFileObject} ;
        Compiler.doCompilation(logger, javaFileObjects);
    }

    public static void doCompilation (TreeLogger logger, JavaFileObject[] javaFileObjects) throws FileNotFoundException{
 
        /*Instantiating the java compiler*/
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        
        /*Create a diagnostic controller, which holds the compilation problems*/
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        
        /**
         * Retrieving the standard file manager from compiler object, which is used to provide
         * basic building block for customizing how a compiler reads and writes to files.
         *
         * The same file manager can be reopened for another compiler task.
         * Thus we reduce the overhead of scanning through file system and jar files each time
         */
        StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(diagnostics, Locale.getDefault(), null);

        /* Prepare a list of compilation units (java source code file objects) to input to compilation task*/
        Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(javaFileObjects);
        String dir = null;;
        String currentDir = System.getProperties().getProperty("user.dir");
        String[] dirs = new String[]{currentDir+"/war/WEB-INF/classes",currentDir+"/WEB-INF/classes"};
        for (String p :dirs){
            File f = new File(p);
            if (f.exists()){
            	dir=p;
            	break;
            }
        }
        if (dir==null){
        	throw new FileNotFoundException();
        }

        /*Prepare any compilation options to be used during compilation*/
        //In this example, we are asking the compiler to place the output files under bin folder.
        String[] compileOptions = new String[]{"-d", dir} ;
        Iterable<String> compilationOptionss = Arrays.asList(compileOptions);
 
        /*Create a compilation task from compiler by passing in the required input objects prepared above*/
        CompilationTask compilerTask = compiler.getTask(null, stdFileManager, diagnostics, compilationOptionss, null, compilationUnits) ;

        //Perform the compilation by calling the call method on compilerTask object.
        boolean status = compilerTask.call();
        

        if (!status){//If compilation error occurs
            /*Iterate through each compilation problem and print it*/
            for (@SuppressWarnings("rawtypes") Diagnostic diagnostic : diagnostics.getDiagnostics()){
                System.out.format("Error on line %d in %s", diagnostic.getLineNumber(), diagnostic);
            }
        }
        try {
            stdFileManager.close() ;//Close the file manager
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String getGenPath(){
        String[] runCommandParts = System.getProperty("sun.java.command").split(" ");
        for (int i = 0; i < runCommandParts.length; i++) {
            if (runCommandParts[i].equals("-gen") && runCommandParts.length>i+1){
                return runCommandParts[i+1];
            }
        }
        return null;
    }

    private static String getCurentDir(){
        return System.getProperties().getProperty("user.dir");
    }
}
